import edu.rit.ds.RemoteEventListener;
import edu.rit.ds.registry.NotBoundException;
import edu.rit.ds.registry.RegistryEvent;
import edu.rit.ds.registry.RegistryEventFilter;
import edu.rit.ds.registry.RegistryEventListener;
import edu.rit.ds.registry.RegistryProxy;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;

/**
 * Class Log provides the log program in the Message Queuing system
 * @author Alan Kaminsky
 * @source P2Pedia example
 * 
 * @contributor Praneeth Pulusani
 */
public class Log
	{
	private static String host;
	private static int port;

	private static RegistryProxy registry;
	private static RegistryEventListener registryListener;
	private static RegistryEventFilter registryFilter;
	private static RemoteEventListener<MQServerEvent> mqserverListener;
	/**
	 * Client Log program. Listens to evnts from the MQServer
	 * @param args
	 * @throws Exception
	 */
	public static void main
		(String[] args)
		throws Exception
		{
		// Parse command line arguments.
		if (args.length != 2) usage();
		String host = args[0];
		int port = parseInt (args[1], "port");

		// Get proxy for the Registry Server.
		try {
		registry = new RegistryProxy (host, port);
		} catch (RemoteException e) {
			throw new RemoteException(
					"There is no Registry server running at given host and port");
		}
		// Export a remote event listener object for receiving notifications
		// from the Registry Server.
		registryListener = new RegistryEventListener()
			{
			public void report (long seqnum, RegistryEvent event)
				{
				listenToMQServer (event.objectName());
				}
			};
		UnicastRemoteObject.exportObject (registryListener, 0);

		// Export a remote event listener object for receiving notifications
		// from MQServer objects.
		mqserverListener = new RemoteEventListener<MQServerEvent>()
			{
			public void report (long seqnum, MQServerEvent event)
				{
				// Print log report on the console.
				System.out.printf ("%s: %s incoming, %s outgoing\n",event.MQServername,
					event.incoming, event.outgoing);
				}
			};
		UnicastRemoteObject.exportObject (mqserverListener, 0);

		// Tell the Registry Server to notify us when a new MQServer object is
		// bound.
		registryFilter = new RegistryEventFilter()
			.reportType ("MQServer")
			.reportBound();
		registry.addEventListener (registryListener, registryFilter);

		// Tell all existing MQServer objects to notify us of queries.
		for (String objectName : registry.list ("MQServer"))
			{
			listenToMQServer (objectName);
			}
		}

	/**
	 * Tell the given MQServer object to notify us of queries.
	 *
	 * @param  objectName  MQServer object's name.
	 *
	 * @exception  RemoteException
	 *     Thrown if a remote error occurred.
	 */
	private static void listenToMQServer
		(String objectName)
		{
		try
			{
			MQServerRef mqserver = (MQServerRef) registry.lookup (objectName);
			mqserver.addListener (mqserverListener);
			}
		catch (NotBoundException exc)
			{
			}
		catch (RemoteException exc)
			{
			}
		}

	/**
	 * Print a usage message and exit.
	 */
	private static void usage()
		{
		System.err.println ("Usage: java Log <host> <port>");
		System.err.println ("<host> = Registry Server's host");
		System.err.println ("<port> = Registry Server's port");
		System.exit (1);
		}

	/**
	 * Parse an integer command line argument.
	 *
	 * @param  arg  Command line argument.
	 * @param  name  Argument name.
	 *
	 * @return  Integer value of <TT>arg</TT>.
	 *
	 * @exception  IllegalArgumentException
	 *     (unchecked exception) Thrown if <TT>arg</TT> cannot be parsed as an
	 *     integer.
	 */
	private static int parseInt
		(String arg,
		 String name)
		{
		try
			{
			return Integer.parseInt (arg);
			}
		catch (NumberFormatException exc)
			{
			System.err.printf ("Log: Invalid <%s>: \"%s\"", name, arg);
			usage();
			return 0;
			}
		}
	}
